package org.emet.jee.console.services.security;

import java.util.List;

import org.emet.jee.BusinessException;
import org.emet.jee.console.dao.security.AuthorityDao;
import org.emet.jee.console.dao.security.RoleDao;
import org.emet.jee.console.dao.security.UserDao;
import org.emet.jee.console.entity.security.Authority;
import org.emet.jee.console.entity.security.Role;
import org.emet.jee.console.entity.security.User;
import org.emet.jee.console.web.form.UserForm;
import org.emet.jee.core.dao.Page;
import org.emet.jee.core.security.springsecurity.SpringSecurityUtils;
import org.hibernate.Hibernate;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.flex.remoting.RemotingDestination;
import org.springframework.security.annotation.Secured;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

/**
 * 安全相关实体的管理类, 包括用户,角色,资源与授权类.
 * 
 * @author calvin
 */
// Spring Service Bean的标识.
@Service
// 默认将类中的所有函数纳入事务管理.
@Transactional
@RemotingDestination
public class SecurityEntityManager {

	private static Logger logger = LoggerFactory.getLogger(SecurityEntityManager.class);

	@Autowired
	private UserDao userDao;
	@Autowired
	private RoleDao roleDao;
	@Autowired
	private AuthorityDao authorityDao;

	// -- User Manager --//
	/**
	 * 根据员工号获得用户
	 */
	@Transactional(readOnly = true)
	@Secured("A_VIEW_USER")
	public User getBySN(String SN) {
		return userDao.findUniqueBy("staffNumber", SN);
	}

	@Transactional(readOnly = true)
	@Secured("A_VIEW_USER")
	public User getUser(Long id) {
		try {
			return userDao.get(id);
		} catch (Exception e) {
			logger.error(e.getMessage(), e);
			throw new BusinessException("获取用户信息时发生异常！", e);
		}
	}

	@Secured("A_MODIFY_USER")
	public void saveUser(User entity) {
		try {
			userDao.save(entity);
		} catch (Exception e) {
			logger.error(e.getMessage(), e);
			throw new BusinessException("保存用户信息时发生错误！", e);
		}
	}

	/**
	 * 删除用户,如果尝试删除超级管理员将抛出异常.
	 */
	@Secured("A_MODIFY_USER")
	public void deleteUser(Long id) {
		if (isSupervisor(id)) {
			logger.warn("操作员{}尝试删除超级管理员用户", SpringSecurityUtils.getCurrentUserName());
			throw new BusinessException("不能删除超级管理员用户");
		}
		if (userDao.get(id) == null)
			throw new BusinessException("不存在该用户！");

		try {
			userDao.delete(id);
		} catch (Exception e) {
			logger.error(e.getMessage(), e);
			throw new BusinessException("删除用户时发生错误！", e);
		}
	}

	/**
	 * 判断是否超级管理员.
	 */
	private boolean isSupervisor(Long id) {
		return id == 1;
	}

	/**
	 * 使用属性过滤条件查询用户.
	 */
	@Transactional(readOnly = true)
	@Secured("A_VIEW_USER")
	public Page<User> searchUser(final Page<User> page, final UserForm criteria) {
		try {
			Page<User> search = userDao.search(page, criteria);
			for (User u : search.getResult()) {
				List<Role> roleList = u.getRoleList();
				for (Role role : roleList) {
					Hibernate.initialize(role);
				}
			}
			return search;

		} catch (Exception e) {
			logger.error(e.getMessage(), e);
			throw new BusinessException("查询时发生错误！", e);
		}
	}

	@Transactional(readOnly = true)
	public User getCurrentUser() {
		String currentUserName = SpringSecurityUtils.getCurrentUserName();
		return findUserByLoginName(currentUserName);
	}

	@Transactional(readOnly = true)
	public User findUserByLoginName(String loginName) {
		try {
			return userDao.findUniqueBy("loginName", loginName);
		} catch (Exception e) {
			logger.error(e.getMessage(), e);
			throw new BusinessException("查询时发生错误！", e);
		}
	}

	public User findEnabledUserByUserName(String loginName) {

		try {
			return userDao.findUnique("from User where loginName = ? and enabled = true", loginName);
		} catch (Exception e) {
			logger.error(e.getMessage(), e);
			throw new BusinessException("查询时发生错误！", e);
		}
	}

	/**
	 * 检查用户名是否唯一.
	 * 
	 * @return loginName在数据库中唯一或等于oldLoginName时返回true.
	 */
	@Transactional(readOnly = true)
	public boolean isLoginNameUnique(String newLoginName, String oldLoginName) {
		return userDao.isPropertyUnique("loginName", newLoginName, oldLoginName);
	}

	// -- Role Manager --//
	@Transactional(readOnly = true)
	@Secured("A_VIEW_ROLE")
	public Role getRole(Long id) {
		try {
			return roleDao.get(id);
		} catch (Exception e) {
			logger.error(e.getMessage(), e);
			throw new BusinessException("获取角色信息时发生异常！", e);
		}
	}

	@Transactional(readOnly = true)
	@Secured("A_VIEW_ROLE")
	public List<Role> getAllRole() {
		try {
			return roleDao.getAll("id", true);
		} catch (Exception e) {
			logger.error(e.getMessage(), e);
			throw new BusinessException("获取所有角色信息时发生异常！", e);
		}
	}

	@Secured("A_MODIFY_ROLE")
	public void saveRole(Role entity) {
		try {
			roleDao.save(entity);
		} catch (Exception e) {
			logger.error(e.getMessage(), e);
			throw new BusinessException("保存角色信息时发生错误！", e);
		}
	}

	@Secured("A_MODIFY_ROLE")
	public void deleteRole(Long id) {
		try {
			roleDao.delete(id);
		} catch (Exception e) {
			logger.error(e.getMessage(), e);
			throw new BusinessException("删除角色时发生错误！", e);
		}
	}

	// -- Authority Manager --//
	@Transactional(readOnly = true)
	public List<Authority> getAllAuthority() {
		try {
			return authorityDao.getAll();
		} catch (Exception e) {
			logger.error(e.getMessage(), e);
			throw new BusinessException("获取所有权限信息时发生异常！", e);
		}
	}
}
